package com.ywk.springCore.lifeCycle.core;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 对于spring的生命周期，
 * 在宏观角度来看，可以分为：
 * 1.实例化前（InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation）、
 * 2.实例化（bean对应的构造方法）、3.实例化后（InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation）、
 * 4.填充属性（spring 属性注入，即 @Autowired/@Value等方式）、5.初始化前（BeanPostProcessor.postProcessBeforeInitialization）、
 * 6.初始化（@PostConstruct/InitializingBean.afterPropertiesSet）、
 * 7.初始化后（BeanPostProcessor.postProcessAfterInitialization）。
 *
 * 在详细角度来看，可以分为：
 * 1.生成 BeanDefinition（通过ClassPathBeanDefinitionScanner#doScan 扫描类文件，此类有一个 includeFilters（从父类继承的）属性
 * 的过滤器，过滤掉没有@Component 直接/间接（ @Repository、@Service、@Controller ）注解的类，生成 BeanDefinition。）
 * 2.合并 BeanDefinition（）
 * 3.加载类   4.实例化前  5.推断构造方法    6.实例化    7.BeanDefinition 的后置处理    8.填充属性
 * 9.执行 Aware（BeanNameAware、BeanClassLoadAware、BeanFactoryAware、ApplicationContextAware）
 * 10.初始化前  11.初始化   12、初始化后。
 *
 * BeanPostProcessor 继承类（idea 快捷键 ctrl+h/ctrl+alt+shift+u）：
 * bean的实例化接口：InstantiationAwareBeanPostProcessor 和 SmartInstantiationAwareBeanPostProcessor
 * bean的初始化接口：BeanPostProcessor 和 MergedBeanDefinitionPostProcessor
 * bean的销毁接口：DestructionAwareBeanPostProcessor（bean销毁前调用，项目关闭或者手动销毁bean都会触发）
 *
 * @Author zbh
 * @Date 2023/4/10
 */
@Component//需要将BeanPostProcessor接口实现类声明为bean，使用<bean>配置或者使用@Component注解，实现类方法才会生效
@Slf4j
public class LifeCycle implements InstantiationAwareBeanPostProcessor,BeanPostProcessor, DestructionAwareBeanPostProcessor {

    /**
     * 实例化前：InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
     * 返回的值不为空, 那么对象的生成阶段直接完成了，如果为空，则走spring源码doCreateBean()创建对象
     *
     * @param beanClass
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("student")){
            log.info("实例化前：{}",beanName);
        }else if (beanName.equals("card")){
            log.info("实例化前：{}",beanName);
        }else if (beanName.equals("handBeanRegistry")){
            log.info("实例化前：{}",beanName);
        }
        return null;
    }
    /**
     * 实例化后：InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
     * false表示实例化后不需要走 spring 的属性注入，true表示还需要属性注入。（即：@Autowired属性注入）
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("student")){
            log.info("实例化后：{}",bean);
        }else if (beanName.equals("card")){
            log.info("实例化后：{}",bean);
        }else if (beanName.equals("handBeanRegistry")){
            log.info("实例化后：{}",bean);
        }


        return true;
    }

    /**
     * 初始化前：BeanPostProcessor.postProcessBeforeInitialization
     * 方法返回值为 bean，@PostConstruct 修饰的方法会执行，方法返回值为 null，@PostConstruct 修饰的方法则不执行
     *
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("student")){
            log.info("初始化前：{}",bean);
        }else if (beanName.equals("card")){
            log.info("初始化前：{}",bean);
        }else if (beanName.equals("handBeanRegistry")){
            log.info("初始化前：{}",bean);
        }
        return bean;
//        return null;
    }

    /**
     *
     * 初始化后：BeanPostProcessor.postProcessAfterInitialization
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("student")){
            log.info("初始化后：{}",bean);
            System.out.println("========================================================================================");
        }else if (beanName.equals("card")){
            log.info("初始化后：{}",bean);
            System.out.println("========================================================================================");
        }else if (beanName.equals("handBeanRegistry")){
            log.info("初始化后：{}",bean);
            System.out.println("========================================================================================");
        }
        return bean;
    }

    /**
     * 销毁前：DestructionAwareBeanPostProcessor.postProcessBeforeDestruction：可以对所有的bean设置销毁（destruction）前的处理操作
     * @param bean
     * @param beanName
     * @throws BeansException
     */
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if(beanName.equals("student")){
            log.info("执行 DestructionAwareBeanPostProcessor.postProcessBeforeDestruction对"+ bean+"销毁前的处理");
        }else if (beanName.equals("card")){
            log.info("执行 DestructionAwareBeanPostProcessor.postProcessBeforeDestruction对"+ bean+"销毁前的处理");
        }else if (beanName.equals("handBeanRegistry")){
            log.info("执行 DestructionAwareBeanPostProcessor.postProcessBeforeDestruction对"+ bean+"销毁前的处理");
        }else if (beanName.equals("myBeanDefinitionRegistry")){
            log.info("执行 DestructionAwareBeanPostProcessor.postProcessBeforeDestruction对"+ bean+"销毁前的处理");
        }
    }

    /**
     * 返回true，一律执行postProcessBeforeDestruction方法
     * 如果返回 false，则不执行postProcessBeforeDestruction方法
     *
     * @param bean
     * @return
     */
    @Override
    public boolean requiresDestruction(Object bean) {
        return true;
    }
}
